/*
 * Part of the NXT bluetooth remote control J2ME applet.
 * Copyright (C) 2007-2008 Alexander Demin, <alexander@demin.ws>
 *
 * This file is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You can redistribute this file and/or modify it under the terms of the GNU
 * General Public License (GPL) as published by the Free Software Foundation;
 * either version 2 of the License, or (at your discretion) any later version.
 * See the accompanying file "COPYING.txt" for more details.
 */
import java.util.*;
import javax.microedition.io.*;
import javax.bluetooth.*;

public class NxtBluetooth implements DiscoveryListener {

   private Vector devices = new Vector();

   private RemoteDevice brick;

   private String url;

   private NxtMidlet.Logger logger;

   public NxtBluetooth( NxtMidlet.Logger aLogger ) {
      logger = aLogger;
   }

   public void deviceDiscovered( RemoteDevice rd, DeviceClass dc ) {
      devices.addElement(rd);
      logger.line( rd.getBluetoothAddress() );
   }

   public void inquiryCompleted( int status ) {
      logger.line( "Inquiry completed" );

      synchronized(this) {
        try { this.notifyAll(); } catch(Exception e) {}
      }
   }

   public void servicesDiscovered( int transId, ServiceRecord[] rec ) {

      // This is hack! We suppose that there is only one SPP service on the brick,
      // so you just get the first record. 

      url = rec[0].getConnectionURL( ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false );

      // This is for debug purpose only. It prints all services found.

      for (int i = 0; i < rec.length; i++) {
          String url = rec[i].getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);

          if( url == null ) continue;

          DataElement serviceName = rec[i].getAttributeValue(0x0100);
          if (serviceName != null)
              logger.line("Service " + serviceName.getValue() + " found " + url);
          else 
              logger.line("Service found " + url);
      }
   }

   public void serviceSearchCompleted( int transId, int respCode ) {
      logger.line( "Service search completed" );
      synchronized(this) {
         try{ this.notifyAll(); } catch(Exception e) {}
      }
   }

   public String getURL() { return url; }

   public void find() throws Exception { 
      try {
         DiscoveryAgent agent = LocalDevice.getLocalDevice().getDiscoveryAgent();

         LocalDevice.getLocalDevice().setDiscoverable(DiscoveryAgent.GIAC);

         logger.line( "Searching devices..." );

         agent.startInquiry( DiscoveryAgent.GIAC, this );

         synchronized(this) {
            try{ this.wait(); } catch(Exception e) {}
         }

         logger.line( "Names..." );

         for(Enumeration en = devices.elements(); en.hasMoreElements(); ) {
             RemoteDevice device = (RemoteDevice)en.nextElement();

             String name = "?";

             try {
                name = device.getFriendlyName(false);
                logger.line( name );
             } catch( java.io.IOException e ) {
                logger.line( e.getMessage() );
             }

             if( name.equals("NXT") )
                brick = device;
         }

         UUID serviceUUID = new UUID(0x1101);    // We will find SPP serives only

         UUID[] uuids = new UUID[] { serviceUUID };

         int attrs[] = new int[] { 0x0100 };

         url = null;

         if( brick != null ) {

            logger.line( "Searching services..." );
            agent.searchServices( attrs, uuids, brick, this );
            synchronized(this) {
               try{ this.wait(); } catch( Exception e ) {}
            }

            if( url == null )
               throw new Exception( "NXT SPP service not found" );

         } else
            throw new Exception( "NXT not found" );

      } catch( BluetoothStateException e ) {
         logger.line( e.toString() );
         throw new Exception( "Bluetooth error" );
      }
   }
}
